// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// S [author] rhyme_lph
// d [email]  rhymelph@gmail.com
// D [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/app_colors.dart';
import 'package:finance_app/src/common/app_spaces.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/format/service_and_product_entity.dart';
import 'package:finance_app/src/entities/invoice_detail_entity.dart';
import 'package:finance_app/src/entities/ocr_attachment_entity.dart';
import 'package:finance_app/src/entities/payment_term_entity.dart';
import 'package:finance_app/src/entities/quotation_detail_entity.dart';
import 'package:finance_app/src/entities/setting_data_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/provider/dashboard/contact/business_contact_detail_provider.dart';
import 'package:finance_app/src/provider/dashboard/credit_note/new_credit_note_provider.dart';
import 'package:finance_app/src/provider/dashboard/invoice/new_invoice_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/router_gen/router_meta.dart';
import 'package:finance_app/src/utils/cash_utils.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/utils/form_utils.dart';
import 'package:finance_app/src/utils/object_utils.dart';
import 'package:finance_app/src/widgets/button/normal_border_button.dart';
import 'package:finance_app/src/widgets/button/normal_popup_button.dart';
import 'package:finance_app/src/widgets/button/normal_text_button.dart';
import 'package:finance_app/src/widgets/common/tag_widget.dart';
import 'package:finance_app/src/widgets/common_app_bar.dart';
import 'package:finance_app/src/widgets/form/add_form.dart';
import 'package:finance_app/src/widgets/form/attach_file_form.dart';
import 'package:finance_app/src/widgets/form/form_edit_status_inherited_widget.dart';
import 'package:finance_app/src/widgets/form/price_form.dart';
import 'package:finance_app/src/widgets/form/service_and_product_form_item.dart';
import 'package:finance_app/src/widgets/form/status_line_form.dart';
import 'package:finance_app/src/widgets/form/text_area_input_form.dart';
import 'package:finance_app/src/widgets/form/value_select_form.dart';
import 'package:finance_app/src/widgets/input/form_input_field.dart';
import 'package:finance_app/src/widgets/wrapper/normal_form_wrapper.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';

export 'package:finance_app/src/entities/quotation_detail_entity.dart';

@RouterMeta(paramName: "newInvoicePage")
class NewInvoicePage extends StatefulWidget {
  final TransactionEntity data;
  final QuotationDetailEntity generate;
  final bool isSelectMode;

  const NewInvoicePage({Key key, this.data, this.generate, this.isSelectMode})
      : super(key: key);

  @override
  _NewInvoicePageState createState() => _NewInvoicePageState();
}

class _NewInvoicePageState extends State<NewInvoicePage>
    with PagePresenter<NewInvoicePage, NewInvoiceProvider> {
  String get title => provider.data == null && pageStatus != PageStatus.loading
      ? S.current.new_invoice
      : provider.isEdit == true
          ? S.current.edit_invoice
          : S.current.invoice;

  Widget get rightButton => listBuilder<bool>(
        selector: (_, __) => __.isEdit == false && __.data != null,
        builder: (BuildContext context, bool value, Widget child) =>
            value ? _buildPopButton() : _buildSaveBtn(),
      );

  @override
  PreferredSizeWidget get appBar => getDefaultAppBar(
          titleWidget: listBuilder<Tuple2<InvoiceDetailEntity, bool>>(
            selector: (_, __) => Tuple2(__.data, __.isEdit),
            builder: (BuildContext context,
                    Tuple2<InvoiceDetailEntity, bool> value, Widget child) =>
                Text(title),
          ),
          actions: [
            rightButton,
          ]);

  @override
  void initState() {
    provider.isSelectMode = widget.isSelectMode;
    provider.currency = Config.defaultCurrency;
    final pro = Providers.get<BusinessContactDetailProvider>(
        RouterGenProviders.businessContactDetailPage, null);
    if (pro != null) {
      provider.client = pro.contact;
      provider.creditValue = null;
      provider.currencyName = provider.currency.key;
      provider.availableCredit = pro.contact.totalUnpaidCredit;
    }
    final creditNote = Providers.get<NewCreditNoteProvider>(
        RouterGenProviders.newCreditNotePage, null);
    if (creditNote != null) {
      provider.client = creditNote.issueTo;
    }
    provider.init(widget.data?.transactionableId);
    provider.generate(widget.generate);
    super.initState();
  }

  Widget _buildPopButton() => listBuilder<Tuple2<bool, List<String>>>(
        selector: (_, __) => Tuple2(
            __.isEdit && __.data.status != 'closed', List.from(__.menuList)),
        builder: (BuildContext context, Tuple2<bool, List<String>> value,
                Widget child) =>
            value.item1 == true
                ? Container()
                : NormalMorePopupButton(
                    onSelect: provider.onSelectMenu,
                    menuList: provider.menuList,
                  ),
      );

  Widget _buildSaveBtn() {
    return listBuilder<bool>(
      selector: (_, __) => pageStatus != PageStatus.loading,
      builder: (BuildContext context, bool value, Widget child) => value == true
          ? NormalSaveTextButton(
              onTap: provider.onSave,
            )
          : Container(),
    );
  }

  @override
  Widget wrapperBody(Widget child) {
    return listBuilder<bool>(
      selector: (_, __) => __.isEdit == true || provider.id == null,
      builder: (BuildContext context, bool value, Widget child) =>
          FormEditStatusInheritedWidget(
        isEdit: value,
        child: child,
      ),
      child: child,
    );
  }

  @override
  Widget get buildWidget => ColoredBox(
        color: Colors.white,
        child: ListView(
          children: [
            listBuilder<String>(
              selector: (_, __) =>
                  __.data?.status == 'open' && __.data?.isOverdue == 1
                      ? 'Overdue'
                      : __.data?.status,
              builder: (BuildContext context, String value, Widget child) =>
                  StatusLineForm(
                status: value,
                model: ReimburseModel.invoice,
              ),
            ),
            listBuilder<String>(
              selector: (_, __) => __.client?.name,
              builder: (BuildContext context, String value, Widget child) =>
                  ValueSelectForm(
                title: S.current.client_name,
                onTap: provider.onChangeClientName,
                value: value,
              ),
            ),
            listBuilder<bool>(
              selector: (_, __) => __.numberHasError,
              builder: (BuildContext context, bool value, Widget child) =>
                  FromInputField(
                controller: provider.invoiceNumberController,
                focusNode: provider.invoiceNumberFocusNode,
                tip: S.current.invoice_number,
                hasError: value,
              ),
            ),
            listBuilder<DateTime>(
              selector: (_, __) => __.date,
              builder: (BuildContext context, DateTime value, Widget child) =>
                  ValueSelectForm(
                title: S.current.issue_date,
                value: ObjectUtils.isNullDefaultFormat<DateTime>(value, null,
                    (data) => DateTimeUtils.formatGlobalDateTime(data)),
                onTap: provider.onChangeIssueDate,
              ),
            ),
            listBuilder<PaymentTermEntity>(
              selector: (_, __) => provider.paymentTerm,
              builder: (BuildContext context, PaymentTermEntity value,
                      Widget child) =>
                  ValueSelectForm(
                title: S.current.payment_term,
                onTap: provider.onChangePaymentTerm,
                value: value?.name,
              ),
            ),
            listBuilder<Tuple2<DateTime, bool>>(
              selector: (_, __) => Tuple2(
                  __.dueDate, __.paymentTerm?.paymentTermType == 'custom'),
              builder: (BuildContext context, Tuple2<DateTime, bool> value,
                      Widget child) =>
                  value.item1 != null || value.item2
                      ? ValueSelectForm(
                          title: S.current.due_date,
                          value: ObjectUtils.isNullDefaultFormat<DateTime>(
                              value.item1,
                              null,
                              (data) =>
                                  DateTimeUtils.formatGlobalDateTime(data)),
                          onTap:
                              provider.paymentTerm?.paymentTermType == 'custom'
                                  ? provider.onChangeDueDate
                                  : null,
                        )
                      : Container(),
            ),
            Stack(
              children: [
                listBuilder<String>(
                  selector: (_, __) => __.quotationNumber?.number,
                  builder: (BuildContext context, String value, Widget child) =>
                      ValueSelectForm(
                    title: S.current.quotation_number,
                    value: value,
                    onTap: provider.onChangeQuotationNumber,
                  ),
                ),
                Align(
                  alignment: Alignment.centerRight,
                  child: listBuilder<bool>(
                    selector: (_, __) => __.isDelivered,
                    builder: (BuildContext context, bool value, Widget child) =>
                        value == true
                            ? Container(
                                margin: EdgeInsets.only(
                                    right: getDp(35), top: getDp(20)),
                                child: BlueTagWidget(
                                  content: S.current.delivered,
                                ),
                              )
                            : Container(),
                  ),
                )
              ],
            ),
            listBuilder<String>(
              selector: (_, __) => __.currency?.name,
              builder: (BuildContext context, String value, Widget child) =>
                  ValueSelectForm(
                title: S.current.currency,
                value: value,
                onTap: provider.onChangeCurrency,
                border: null,
              ),
            ),
            AppSpaces.grayH6,
            listBuilder<int>(
              selector: (_, __) =>
                  List<ServiceAndProductEntity>.from(__.serviceAndProductList)
                      .length,
              builder: (BuildContext context, int value, Widget child) =>
                  value != 0
                      ? Column(
                          children: [
                            ...List.generate(
                                value,
                                (index) => listBuilder<
                                        Tuple4<ServiceAndProductEntity, int,
                                            num, SettingDataTax>>(
                                      selector: (_, __) => Tuple4(
                                          __.serviceAndProductList[index],
                                          __.serviceAndProductList[index]
                                              .number,
                                          __.serviceAndProductList[index]
                                              .discountedAmount,
                                          __.serviceAndProductList[index].tax),
                                      builder: (BuildContext context,
                                              Tuple4<ServiceAndProductEntity,
                                                      int, num, SettingDataTax>
                                                  value,
                                              Widget child) =>
                                          ServiceAndProductFormItem(
                                        onTap: () =>
                                            provider.onSelectItem(value.item1),
                                        productEntity: value.item1,
                                        hasError: false,
                                        showHeader: index == 0,
                                        isLastElement: provider
                                                    .serviceAndProductList
                                                    .length ==
                                                index + 1 &&
                                            provider.id != null &&
                                            provider.isEdit == false,
                                      ),
                                    ))
                          ],
                        )
                      : ValueSelectForm(
                          title: S.current.item__quantity__amount__tax_rate,
                          onTap: provider.onAddItem,
                        ),
            ),
            AddForm(
              title: S.current.add_item,
              onTap: provider.onAddItem,
            ),
            AppSpaces.grayH6,
            NormalFormWrapper(
              child: Column(
                children: [
                  _buildEditCredit(),
                  _buildTotal(),
                  _buildIncludes(),
                ],
              ),
            ),
            listBuilder<bool>(
              selector: (_, __) => __.data == null || __.isEdit,
              builder: (BuildContext context, bool value, Widget child) => value
                  ? Container()
                  : Column(
                      children: [
                        AppSpaces.grayH05,
                        NormalFormWrapper(
                            child: Column(
                          children: [
                            _buildCredit(),
                            AppSpaces.h20,
                            _buildPayment(),
                            AppSpaces.h20,
                            _buildBalance(),
                          ],
                        )),
                      ],
                    ),
            ),
            listBuilder<bool>(
              selector: (_, __) => __.availableCredit > 0,
              builder: (BuildContext context, bool value, Widget child) =>
                  Visibility(
                visible: value,
                child: AddForm(
                  title: S.current.apply_credit,
                  topPadding: 0,
                  onTap: provider.onAddCredit,
                ),
              ),
            ),
            AppSpaces.grayH6,
            TextAreaInputForm(
              title: S.current.additional_notes_optional,
              controller: provider.notesController,
              focusNode: provider.notesFocusNode,
            ),
            NormalFormWrapper(
              child:
                  listBuilder<Tuple2<List<String>, List<OcrAttachmentEntity>>>(
                selector: (_, __) => Tuple2(
                    List.from(__.files), List.from(__.attachments ?? [])),
                builder: (BuildContext context,
                        Tuple2<List<String>, List<OcrAttachmentEntity>> value,
                        Widget child) =>
                    AttachFileForm(
                  onAdd: provider.onAddAttachment,
                  files: value.item1,
                  onSelectFile: provider.onSelectFile,
                  attachments: value.item2,
                  onSelectAttachment: provider.onSelectAttachment,
                ),
              ),
            ),
            AppSpaces.h30,
            FormStatusWidget(
              enable: Container(),
              disable: listBuilder<Tuple2<bool, bool>>(
                selector: (_, __) => Tuple2<bool, bool>(
                    __.menuList.contains("See Payment"),
                    __.menuList.contains("Receive Payment")),
                builder: (BuildContext context, Tuple2<bool, bool> value,
                        Widget child) =>
                    Column(
                  children: [
                    if (value.item1 == true) ...[
                      NormalBorderButton(
                        title: S.current.see_payment,
                        onTap: provider.onSeePayment,
                        isFit: true,
                      ),
                      AppSpaces.h30,
                    ],
                    if (value.item2 == true) ...[
                      NormalBorderButton(
                        title: S.current.receive_payment,
                        onTap: provider.onRecordPayment,
                        isFit: true,
                      ),
                      AppSpaces.h30,
                    ],
                    SizedBox(
                      height: getDp(30),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
      );

  Widget _buildEditCredit() {
    return listBuilder<Tuple2<double, bool>>(
      selector: (_, __) =>
          Tuple2<double, bool>(__.creditUsed, __.isEdit || __.data == null),
      builder:
          (BuildContext context, Tuple2<double, bool> value, Widget child) =>
              value.item1 == null
                  ? Container()
                  : value.item2
                      ? PressedOpacityButton(
                          onPressed: provider.onAddCredit,
                          padding: EdgeInsets.only(bottom: getDp(25)),
                          child: PriceForm(
                            isHighlight: true,
                            title: S.current.credit_,
                            amount: CashUtils.formatCashAmount(-value.item1),
                          ),
                        )
                      : Container(),
    );
  }

  Widget _buildCredit() {
    return listBuilder<double>(
      selector: (_, __) => __.creditUsed,
      builder: (BuildContext context, double value, Widget child) =>
          value == null
              ? Container()
              : PriceForm(
                  title: S.current.credit_,
                  amount: CashUtils.formatCashAmount(-value),
                ),
    );
  }

  Widget _buildTotal() {
    return listBuilder<double>(
      selector: (_, __) =>
          __.isEdit || __.data == null ? __.totalDiscount : __.total,
      builder: (BuildContext context, double value, Widget child) => PriceForm(
        title: S.current.total,
        amount: CashUtils.formatCashAmount(value),
      ),
    );
  }

  Widget _buildPayment() {
    return listBuilder<num>(
      selector: (_, __) =>
          (__.data.total ?? 0) - (__.data.unpaid + (__.creditUsed ?? 0)),
      builder: (BuildContext context, num value, Widget child) => PriceForm(
        title: S.current.payment,
        textColor: value != 0 ? aceGreenColor : null,
        amount: '- ${CashUtils.formatCashAmount(value)}',
      ),
    );
  }

  Widget _buildBalance() {
    return listBuilder<num>(
      selector: (_, __) => __.data.unpaid,
      builder: (BuildContext context, num value, Widget child) => PriceForm(
        title: S.current.balance,
        textColor: value == 0 ? aceGreenColor : null,
        amount: CashUtils.formatCashAmount(value),
      ),
    );
  }

  Widget _buildIncludes() {
    return Align(
      alignment: Alignment.centerRight,
      child: listBuilder<double>(
          builder: (BuildContext context, double value, Widget child) =>
              Config.currentCompany.enableGst == 0
                  ? Container()
                  : Container(
                      padding: EdgeInsets.only(top: 2),
                      child: Text(
                        '${S.current.includes_gst} ${CashUtils.formatCashAmount(value)}',
                        style: TextStyle(
                          color: aceDarkGrayColor,
                          fontSize: getSp(14),
                          fontWeight: FontWeight.w400,
                          height: 1,
                        ),
                      ),
                    ),
          selector: (_, __) => __.includesGST + __.gst),
    );
  }
}
